package apis

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"

	"gitee.com/kobeyyf/local_service/handler"
	"github.com/russross/blackfriday/v2"
)

const (
	PATH_FILESERVER = "/file_server"

	openFileFaield = `<h1>读取文件失败%s: %s</h1>`

	fileLineTemp = `<a href="%s/file_server?path=%s/%s">%s</a>:  文件大小: %s  类型: %s <br>`
)

type FileServer struct {
}

func (api *FileServer) Path() string {
	return "/file_server"
}

func (api *FileServer) Helper() string {
	return "返回目录下的文件列表或者文件内容,参数: path=/"
}

func (api *FileServer) HandlerFunc(c *handler.Context) *handler.Respone {

	err := c.R.ParseForm()
	if err != nil {
		fmt.Println("解析文件失败")
		fmt.Println("err ")
		return nil
	}
	path := c.R.FormValue("path")
	if path == "" {
		path = "~/"
	}

	state, err := os.Stat(path)
	if err != nil {
		c.W.Write([]byte(fmt.Sprintf(openFileFaield, path, err.Error())))
		return nil
	}

	if state.IsDir() {
		fd, err := os.Open(path)
		if err != nil {
			c.W.Write([]byte(fmt.Sprintf(openFileFaield, path, err.Error())))
			return nil
		}
		defer fd.Close()

		names, err := fd.Readdir(-1)
		if err != nil {
			c.W.Write([]byte(fmt.Sprintf(openFileFaield, path, err.Error())))
			return nil
		}

		addr := "http://" + c.R.Host

		buf := bytes.NewBuffer(nil)

		for _, name := range names {
			genFileLink(buf, addr, path, name)
		}
		c.W.Write(buf.Bytes())

		return nil
	}
	if state.Mode()&os.ModeType == 0 {
		fd, err := os.Open(path)
		if err != nil {
			c.W.Write([]byte(fmt.Sprintf(openFileFaield, path, err.Error())))
			return nil
		}
		defer fd.Close()

		// 如果文件是md
		if filepath.Ext(path) == ".md" {
			buf, err := ioutil.ReadAll(fd)
			if err != nil {
				c.W.Write([]byte(fmt.Sprintf(openFileFaield, path, err.Error())))
				return nil
			}
			output := blackfriday.Run(buf)
			c.W.Header().Add("Access-Control-Allow-Origin", "*")
			c.W.Header().Add("Content-Type", "text/html; charset=utf-8")
			c.W.WriteHeader(200)
			c.W.Write(output)

			return nil
		}

		// 直接下载文件
		c.W.Header().Add("Access-Control-Allow-Origin", "*")
		c.W.Header().Add("Content-Disposition", fmt.Sprintf("attachment;filename=%s", state.Name()))
		c.W.WriteHeader(200)
		io.Copy(c.W, fd)
		return nil
	}

	// 其他类型文件不支持, 返回文件信息
	c.W.Write([]byte(fmt.Sprintf(" 文件名称:%s\n 文件类型: %s\n 文件大小: %d\n 编辑时间: %s\n ", state.Name(), state.Mode().String(), state.Size(), state.ModTime().String())))

	return nil

}

func genFileLink(buf *bytes.Buffer, addr, path string, info os.FileInfo) {
	buf.WriteString(fmt.Sprintf(fileLineTemp, addr, path, info.Name(), info.Name(), parseSize(info.Size()), info.Mode().String()))
}

const (
	oneKb = 1024
	oneMb = 1024 * 1024
	oneGb = 1024 * 1024 * 1024
)

func parseSize(size int64) string {
	if size < oneKb {
		return fmt.Sprintf("%dB", size)
	}
	if size < oneMb {
		return fmt.Sprintf("%dKb", size/oneKb)
	}
	if size < oneGb {
		return fmt.Sprintf("%dMb", size/oneMb)
	}
	return fmt.Sprintf("%dGb", size/oneGb)

}
